package com.hello.pet.config.security;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hello.pet.config.security.utils.HttpUtils;
import com.hello.pet.config.security.utils.JwtTokenUtils;
import com.hello.pet.service.system.model.User;
import com.hello.pet.service.system.param.WxLoginParam;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * 启动登录认证流程过滤器
 */
public class WxLoginFilter extends AbstractAuthenticationProcessingFilter {

	/**
	 * 绑定主配置类的身份认证管理器
	 * @param authManager
	 */
	public WxLoginFilter(AuthenticationManager authManager) {
		super(new AntPathRequestMatcher("/wxLogin", "POST"));
		super.setAuthenticationManager(authManager);
    }

	/**
	 * @param request
	 * @param response
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		String body = getBody(request);
		JSONObject jsonObject = JSONUtil.parseObj(body);
		WxLoginParam wxLoginParam = new WxLoginParam(jsonObject.getStr("code"),JSONUtil.toBean(jsonObject.getStr("user"), User.class));
		WxAuthenticatioToken authRequest = new WxAuthenticatioToken(wxLoginParam,null);
		setDetails(request, authRequest);
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	protected void setDetails(HttpServletRequest request, WxAuthenticatioToken authRequest) {
		authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
	}

	/**
	 * 通过认证之后的操作
	 * @param request
	 * @param response
	 * @param chain
	 * @param authResult
	 * @throws IOException
	 * @throws ServletException
	 */
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException {
		// 存储登录认证信息到上下文
		SecurityContextHolder.getContext().setAuthentication(authResult);
		// 记住我服务
		getRememberMeServices().loginSuccess(request, response, authResult);
		// 触发事件监听器
		if (this.eventPublisher != null) {
			eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
		}
		// 生成并返回token给客户端，后续访问携带此token
		WxAuthenticatioToken token = new WxAuthenticatioToken(JwtTokenUtils.generateToken(authResult));
		HttpUtils.write(response, token);
	}
	
	/** 
	 * 获取请求Body
	 * @param request
	 * @return
	 */
	public String getBody(HttpServletRequest request) {
		StringBuilder sb = new StringBuilder();
		InputStream inputStream = null;
		BufferedReader reader = null;
		try {
			inputStream = request.getInputStream();
			reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
			String line = "";
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}
}
